アプリケーション・プログラムで複数回使用される単一のSQL文をカプセル化します。TTCmdは、ODBC HSTMTハンドルの付加価値C++ラッパーとみなすことができます。
なし
void Prepare (TTConnection*, const char* sqlP,
const char* explanationP, TTStatus&)
TTCmdを使用する前に、SQL文(SELECT、INSERT、UPDATEまたはDELETE)を関連付ける必要があります。この関連付けはPrepareメソッドを使用して行われます。また、Prepareメソッドは、SQL文が効率的に実行されるように、SQL文のコンパイルおよび最適化も行います。
Prepareメソッドは文を実行するのではなく、単に文をTTCmdオブジェクトに関連付け、文の実行に使用される計画を決定します。
通常、TimesTenでは、性能のために文はパラメータ化されます。次のようなSQL文を考えてみます。
SELECT col1 FROM table1 WHERE C = 10
SELECT col1 FROM table1 WHERE C = 11
これよりも、パラメータ化された1つの文を準備し、それを複数回実行した方がはるかに効率的です。
SELECT col1 FROM table1 WHERE C = ?
「?」の値は、後述のsetParamメソッドを使用して実行時に指定されます。
ODBCを直接使用する場合と違い、列またはパラメータを明示的にSQL文にバインドする必要はありません。TTCmdは、準備する際にすべての必要な列とパラメータを自動的に定義しバインドします。
Prepareは相対的に負荷の高い操作であることに注意してください。アプリケーションによって、(TTConnection::Connectを使用して)TimesTenへの接続が確立される際に、その接続に関連付けられたすべてのTTCmdオブジェクトが準備されます。
例外が有効な場合は、エラーが発生するとTTStatusオブジェクトが例外としてスローされます。例外が無効な場合は、メソッドから返される際に、発生したエラーに関する情報が、最後のパラメータとしてメソッドに渡されたTTStatus&オブジェクトに格納されます。
void Execute (TTStatus&)
実行のために準備されたSQL文を起動します。
必要なパラメータ値がsetParamメソッドによって定義された後、Executeを使用して、Prepareメソッドによって事前に準備済のSQL文を起動します。
SQL文がSELECT文の場合は、このメソッドによって問合せが実行されますが、結果セットから行が返されません。FetchNextメソッドを使用すると、結果セットから一度に1行ずつフェッチされます。該当するすべての行がフェッチされたら、Closeメソッドを起動して結果セットを閉じる必要があります。SELECT以外のSQL文の場合は、カーソルがオープンされないため、Closeメソッドをコールする必要はありません。
例外が有効な場合は、エラーが発生するとTTStatusオブジェクトが例外としてスローされます。例外が無効な場合は、メソッドから返される際に、発生したエラーに関する情報が、最後のパラメータとしてメソッドに渡されたTTStatus&オブジェクトに格納されます。
int ExecuteImmediate (TTConnection*, const char * sqlP,
TTStatus & stat)
事前に準備されていないSQL文を起動します。
たとえばDDL文(CREATE TABLE、DROP TABLEなど)や、使用頻度が低く結果セットを返さないDML文(DELETE FROM <table name>など)のように、数回だけ実行されるSQL文については、Prepare/ExecuteのかわりにExecuteImmediateを使用すると便利です。
ExecuteImmediateは、結果セットを返すSQL文と互換性がありません。また、ExecuteImmediateによって実行された文は、後でgetRowCount(DML操作によって影響を受けた行の数を取得する)を使用して問い合せることができません。このため、ExecuteImmediateは自動的にgetRowCount()をコールし、その値がこのメソッドの整数の戻り値となります。
int FetchNext (TTStatus & stat)
Executeを使用して準備済のSQL SELECT文を実行した後、FetchNextメソッドを使用して、応答セットから一度に1行ずつフェッチします。
応答セットから1行をフェッチした後に、オーバーロードされた様々なバージョンのgetColumnメソッド(後述)を使用して、現在の行から値をフェッチします。
応答セットに行がなくなると、FetchNextは1を返します。行が返されると、FetchNextは0を返します。
Executeメソッドを使用してSELECTを実行した後、要求されるすべての行がフェッチされてから、Closeメソッドで応答セットを閉じる必要があります。Closeメソッドをコールした後は、FetchNextメソッドを使用して応答セットからそれ以上の行をフェッチできないことに注意してください。
例外が有効な場合は、エラーが発生するとTTStatusオブジェクトが例外としてスローされます。例外が無効な場合は、メソッドから返される際に、発生したエラーに関する情報が、最後のパラメータとしてメソッドに渡されたTTStatus&オブジェクトに格納されます。
void Close (TTStatus&)
Executeメソッドを使用してSQL SELECT文を実行すると、応答セットから行をフェッチするために使用できるカーソルがオープンされます。アプリケーションでの行のフェッチが完了したら、Closeメソッドを使用してカーソルをクローズする必要があります。
応答セットのクローズに失敗すると、行のロックが保持される時間が長くなりすぎるため、同時実行性の問題、メモリ・リークおよびその他のエラーが発生する可能性があります。
例外が有効な場合は、エラーが発生するとTTStatusオブジェクトが例外としてスローされます。例外が無効な場合は、メソッドから返される際に、発生したエラーに関する情報が、最後のパラメータとしてメソッドに渡されたTTStatus&オブジェクトに格納されます。
void Drop (TTStatus&)
準備済のSQL文を今後使用しない場合は、Dropメソッドをコールして、その文とそれに関連付けられたリソースを解放できます。再度Prepareをコールすると、TTCmdオブジェクトを別の文に再利用できます。
複数のTTCmdオブジェクトを使用して複数のSQL文を実行した方が、はるかに効率的です。特定のSQL文を今後使用しないことが確実な場合にのみ、Dropメソッドを使用してください。
例外が有効な場合は、エラーが発生するとTTStatusオブジェクトが例外としてスローされます。例外が無効な場合は、メソッドから返される際に、発生したエラーに関する情報が、最後のパラメータとしてメソッドに渡されたTTStatus&オブジェクトに格納されます。
int getRowCount()
このメソッドをExecuteの直後にコールして、直前に実行されたSQL操作の影響を受けた行の数を返すことができます。たとえば、10行を削除するDELETE文が実行された後には、getRowCountは10を返します。
void setMaxRows (const int nRows, TTStatus &stat)
結果セット内の行数が、設定された上限を超える場合、設定された最大行数を超えてフェッチすると、文はSQL_NO_DATA_FOUNDを返します。つまり、eof()メソッドがコールされると、TTCmdオブジェクトはTRUEを返します。デフォルトでは、すべての行が返されます。すべての行を返すように制限をリセットするには、nRowsを0に設定してsetMaxRows()をコールします。この制限はSELECT文に対してのみ意味があります。
int getMaxRows (TTStatus &stat)
SELECT文によってこのTTCmdコールから返される行数について現在設定されている上限を返します。戻り値0は、すべての行が返されることを示します。
void setParamNull (int i)
「setParam」を参照してください。
void setParam (int i, ...)
この項では、オーバーロードされたすべてのsetParamメソッドについて説明します。
準備済のSQL文を実行する前に、setParamメソッドを使用してパラメータの値を設定します。SQL文は、使用前にPrepareメソッドで準備され、Executeメソッドで実行されます。SQL文にパラメータ・マーカー(リテラル定数が有効である位置で使用される?文字)が含まれている場合、そのSQL文を実行するには、それらのパラメータに値を割り当てる必要があります。文を実行する前に、setParamメソッドを使用して各パラメータの値を定義します。
setParamに最初に渡される引数は、設定されるパラメータの位置です。SQL文の最初(一番左)のパラメータはパラメータ1です。setParamに2番目に渡される引数はパラメータの値です。オーバーロードされた様々なバージョンのsetParamは、2番目の引数で様々なデータ型を受け入れます。
アプリケーションでsetParamNullメソッドを使用して、特定のパラメータの値をSQLのNULL値に指定できます。
このバージョンのTTClassesライブラリは、大規模な変換セットをサポートしません。準備済のSQLのパラメータごとに、オーバーロードされた適切なバージョンのsetParamをコールする必要があります。誤ったバージョンをコールする(たとえば、整数パラメータをchar*値に設定しようとする)と、プログラム障害が発生するおそれがあります。
setParamに渡された値は、TTCmdオブジェクトによって保守される内部バッファにコピーされます。これらのバッファは静的に割り当てられ、Prepareメソッドによってバインドされます。パラメータ値はsetParamのコール時にsetParamに渡される値であって、後続のExecuteメソッドのコール時の値ではありません。
表3.1に、サポートされるSQLデータ型と、各パラメータ型での使用に適したsetParamのバージョンを示します。
表に示されていないSQLデータ型は、このバージョンのTTClassesではサポートされないことに注意してください。
void getColumn (int i, ...)
「isColumnNull」を参照してください。
bool getColumnNullable (int i, ...)
「isColumnNull」を参照してください。
bool isColumnNull (int i)
この項では、オーバーロードされたgetColumnおよびgetColumnNullableメソッドのすべてのバージョンについて説明します。
getColumnおよびgetColumnNullableメソッドを使用して、応答セットの現在の行の列値をフェッチできます。getColumnおよびgetColumnNullableメソッドを使用するには、まずFetchNextメソッドを使用して、SELECT文の応答セットから最初(または次)の行をフェッチする必要があります。SQL文はExecuteメソッドを使用して実行されます。
isColumnNullメソッドは、列値がNULLかどうか調べるもう1つの方法です。
getColumnメソッドは、特定の列に関連付けられた値を返します。列は序数で参照され、「1」はSELECT文で指定された最初の列を示します。すべての場合において、getColumnメソッドに渡される最初の引数は、値がフェッチされる列の序数です。getColumnメソッドに渡される2番目の引数は、指定された列の値を受け取る変数のポインタです。この引数の型は、返される列の型に依存します。
getColumnNullableメソッドはgetColumnメソッドに類似しています。ただし、getColumnNullableメソッドはgetColumnの動作に加え、列の値がSQLのNULL擬似値であるかどうかも返します。列の値がNULLである場合、2番目のパラメータの値は特徴的な値(-9999など)に設定され、メソッドの戻り値はTRUEとなります。列の値がNULLでない場合、2番目のパラメータが指す変数で列の値が返され、getColumnNullableメソッドはFALSEを返します。
このバージョンのTTClassesライブラリは、大規模な変換セットをサポートしません。準備済のSQLの出力列ごとに、オーバーロードされた適切なバージョンのgetColumnをコールする必要があります。誤ったバージョンをコールする(たとえば、整数の列をchar*値にフェッチしようとする)と、プログラム障害が発生するおそれがあります。
整数型のメソッドには、SQLTINYINT、SQLSMALLINT、SQLINTEGERおよびSQLBIGINTのいずれかの関数が含まれています。これらのメソッドは、たとえばNUMBER(p)やNUMBER(p,0)など、スケール・パラメータが0(ゼロ)に設定された列にのみ適しています。前述の関数の精度範囲を次に示します。
アプリケーションがデータベースから情報を取得するために使用する変数に列内のすべての値が適合するようにするには、表のデータ型NUMBER(p)の列すべてに対して常にSQLBIGINTを使用します。ここで、0 <= p <= 18です。次に例を示します。
getColumn(int i, SQLBIGINT*)
表3.2に、サポートされるSQLデータ型と、各パラメータ型での使用に適したgetColumnのバージョンを示します。
このリリースのTTClassesライブラリでは、他のSQLデータ型はサポートされません。
int getColumnLength (int cno)
列# cnoの長さを返します。通常、VARBINARYまたはNVARCHAR2型の列にアクセスする場合のみ有効です。返される値は、0から列の精度です(後述のgetColumnPrecisionメソッドを参照)。
void setQueryTimeout (const int nSecs, TTStatus&)
このメソッドでは、必要に応じて、問合せでタイムアウト値を設定して、アプリケーションによって長時間実行問合せを停止できます。
デフォルトの問合せタイムアウト値は存在しないことに注意してください。
プログラムで複数回実行される各SQL文には、独自のTTCmdオブジェクトが必要です。これらのTTCmdオブジェクトは、プログラムの初期化時にそれぞれ1回準備され、プログラムの実行時にExecute()で複数回実行されます。
ExecuteImmediate()メソッドは、1回だけ実行する必要のあるデータベース操作でのみ使用します。ExecuteImmediate()はどのタイプのSELECT文とも互換性がなく(かわりに、すべての問合せでPrepare() + Execute()を使用する必要があります)、INSERT/UPDATE/DELETE文とも互換性がないことに注意してください。後で、INSERT/UPDATE/DELETE文に対して、挿入/更新/削除された行数を調べるために、getRowcount()によって問合せが実行されます。これらの制限は、一部の状況(表の作成または削除など)を除き、ExecuteImmediate()の使用を避けるために課されています。
準備済のTTCmdオブジェクトの、バインドされた入力パラメータおよび出力列のプロパティについて問い合せる場合に有効なメソッドがいくつかあります。通常、これらのメソッドでは、文が事前に準備されている場合にのみ、有効な結果が得られます。
int getNParameters ()
入力パラメータの数を返します。
int getNColumns ()
出力列の数を返します。
int getParamType (int pno)
パラメータ# pnoのデータ型を返します。返される値は、<sql.h>に見られる、パラメータのODBC型(SQL_INTEGER、SQL_REAL、SQL_BINARY、SQL_CHARなど)です。その他のTimesTen型(SQL_WCHAR、SQL_WVARCHAR)は、TimesTenヘッダー・ファイル<timesten.h>で見られます。
int getColumnType (int cno)
列# cnoのデータ型を返します。返される値は、<sql.h>に見られる、パラメータのODBC型(SQL_INTEGER、SQL_REAL、SQL_BINARY、SQL_CHARなど)です。その他のTimesTen型(SQL_WCHAR、SQL_WVARCHAR)は、TimesTenヘッダー・ファイル<timesten.h>で見られます。const char * getColumnName (int cno)
列# cnoの名前を返します。
int getColumnPrecision (int cno)
列# cnoの精度を返します。通常、この値は、表のCHAR、VARCHAR2、BINARY、VARBINARY、NCHARおよびNVARCHAR2型の列から出力を生成する場合にのみ重要です。
TimesTenは、挿入、更新および削除のバッチ操作のためにODBC関数SQLBindParamsをサポートし、TTClassesはSQLBindParamsへのインタフェースを提供します。
TTClassesでのバッチ操作は、非バッチ操作と同様に実行されます。最初に、SQL文がPrepareBatch()によってコンパイルされます。次に、その文の各パラメータが、BindParameter()によって値の配列にバインドされます。最後に、ExecuteBatch()によって文が実行されます。Prepare()によって文のコンパイルの実行とすべてのパラメータのバインドの自動実行が行われ、またExecute()によって文の実行が行われる、通常のTTClasses(非バッチ)操作との類似性に注意してください。
バッチ操作機能の使用例は、TTClassesサンプル・プログラムbulktest.cpp
を参照してください。
この項では、TTClassesユーザー向けに、バッチの挿入/更新/削除機能を公開するTTCmdメソッドについて説明します。
void PrepareBatch(TTConnection*, const char * sqlP,
TTCmd::TTCMD_USER_BIND_LEVEL level,
unsigned short batchSize, TTStatus&)
PrepareBatch()は、INSERT/UPDATE/DELETE文のバッチ操作に使用されるPrepare()の類似メソッドです。この関数のTTConnection*、const char*sqlPおよびTTStatus&パラメータは、Prepare()の場合と同様に使用されます。
level
パラメータに有効な値は次の1つのみです。
TTCmd::TTCMD_USER_BIND_PARAMS
batchSizeパラメータは、後続のExecuteBatch()のコールによって実行される挿入/更新/削除操作の最大数を指定します。
void BindParameter(int pno, unsigned short batchSize,
<TYPE>*, [SQLLEN*], TTStatus&)
この項では、オーバーロードされた様々なBindParameterメソッドについて説明します。
BindParameterメソッドは、PrepareBatch()によってコンパイルされた文について、値の配列(各パラメータに1つ)をバインドするために使用されます。このコールのbatchSizeパラメータは、PrepareBatch()で指定されたbatchSizeの値と一致する必要があります。同様に、バインドする配列は少なくともこの大きさである必要があります。各パラメータにバインドする正しい型の判別は、ユーザーに一任されています。誤った型をバインドすると、TTLog::TTLOG_ERRロギング・レベルのTTClassesグローバル・ロギング機能に実行時エラーが書き込まれることに注意してください。
ExecuteBatch()を起動するたびに、ユーザー・アプリケーションで事前にこれらの配列に有効なパラメータ値を設定する必要があります。
4つのSQL型(SQL_[VAR]BINARYおよびSQL_W[VAR]CHAR)については、パラメータ値の長さを保持するために、追加のSQLLEN*パラメータ(SQLLENの配列)が必要です。この追加配列は少なくともbatchSizeの長さであり、ExecuteBatch()のコール前に、有効な長さの値が設定されている必要があります。
表3.3に、サポートされるSQLデータ型と、各パラメータ型での使用に適したBindParameterのバージョンを示します。
setParamLength(int pno, unsigned short rowno, int len)
setParamNull(int pno, unsigned short rowno)
これら2つのメソッドは、ExecuteBatch()をコールする前に、バインドされたパラメータ値の1つの長さまたはNULLであることを設定します。setParamLengthの最初のパラメータpnoは文内のどのパラメータを設定するかを指定し、2番目のパラメータrownoは長さを設定する行を指定します。3番目のパラメータlenは、設定する長さを指定します。
SQL_[VAR]BINARYおよびSQL_W[VAR]CHAR以外の型については、ExecuteBatch()のコール前に値の長さ/NULLであることを明示的に設定するために使用できるメソッドはこの2つだけです。それら4つの型については、それらの型に対するBindParameter()コールの4番目のパラメータであったSQLLEN*配列の操作によって、長さとNULLであることを明示的に設定することもできます。
void ExecuteBatch(unsigned short numRows, TTStatus&)
このメソッドはバッチ内の更新された行数を返します。この数は、ODBC SQLSetParamsコールからの*pirowを表します。
PrepareBatch()によってSQL文を準備し、そのSQL文の各パラメータ(「?」)に対してBindParameter()をコールした後、ExecuteBatch()を使用してその文をnumRows回実行します。numRowsの値は、PrepareBatch()およびBindParameter()のコールで指定したbatchSizeを超えてはなりません。ただし、アプリケーション・ロジックでの必要に応じて、numRowsをbatchSizeより小さくすることはできます。
アプリケーションでは、ExecuteBatch()をコールする前に、BindParameter()でバインドされたパラメータの配列に有効な値を設定する必要があります。必要に応じて、setParamNull(int pno, int rowno)によってNULL値を指定できます。
install_dir/demo/ttclasses
にあるデモbulktest.cpp
で、ExecuteBatch()の使用方法が示されます。また、例3.6にも、ExecuteBatch()の使用方法を示します。
2つの列を持つ表を作成します。
CREATE TABLE batch_table (a TT_INTEGER, b VARCHAR2(100));
サイズが50のバッチで表の行を移入します。
#define BATCH_SIZE 50
#define VARCHAR_SIZE 100
int int_array[BATCH_SIZE];
char char_array[BATCH_SIZE][VARCHAR_SIZE];
// Prepare the statement
TTCmd insert;
TTConnection connection;
TTStatus stat;
// (assume a connection has already been established)
try {
insert.PrepareBatch (&connection,
(const char*)"insert into batch_table values (?,?)",
TTCmd::TTCMD_USER_BIND_PARAMS,
BATCH_SIZE
stat);
// Commit the prepared statement
connection.Commit(stat);
// Bind the arrays of parameters
insert.BindParameter(1, BATCH_SIZE, int_array, stat);
insert.BindParameter(2, BATCH_SIZE, char_array, stat);
// Execute 5 batches, inserting 5 * BATCH_SIZE rows into
// the database
for (int iter = 0; iter < 5; iter++)
{
// Populate the value arrays with values.
// (A better way of putting meaningful data into
// the database is to read values from a file,
// rather than generating them arbitrarily.)
for (int i = 0; i < BATCH_SIZE; i++)
{
int_array[i] = i * iter + i;
sprintf(char_array[i], "varchar value # %d", i*iter+ i);
}
// Execute the batch insert statement,
// which inserts the entire contents of the
// integer and char arrays in one operation.
int num_ins = insert.ExecuteBatch(BATCH_SIZE, stat);
cerr << "Inserted " << num_ins << " rows." << endl;
connection.Commit(stat);
} // for iter
たとえば、列の1つに一意制約が指定されている場合などは、行数(この例ではnum_ins
)をBATCH_SIZE
よりも少なくすることができます。この場合は、トランザクションをロールバックし、次のようなコードを使用します。
for (int iter = 0; iter < 5; iter++)
{
// Populate the value arrays with values.
// (A better way of putting meaningful data into
// the database is to read values from a file,
// rather than generating them arbitrarily.)
for (int i = 0; i < BATCH_SIZE; i++)
{
int_array[i] = i * iter + i;
sprintf(char_array[i], "varchar value # %d", i*iter+i);
}
// now we execute the batch insert statement,
// which does the work of inserting the entire
// contents of the integer and char arrays in
// one operation
int num_ins = insert.ExecuteBatch(BATCH_SIZE, stat);
cerr << "Inserted " << num_ins << " rows (expected " <<
<< BATCH_SIZE << " rows)." << endl;
if (num_ins == BATCH_SIZE) {
cerr << "Committing batch" << endl;
connection.Commit(stat);
}
else {
cerr << "Some rows were not inserted as expected, rolling back "
<< "transaction." << endl;
connection.Rollback(stat);
break; // jump out of batch insert loop
}
} // for iter
SQLParamOptionsについては、ODBCのマニュアルも参照してください。TTCmd::ExecuteBatchの整数出力は、SQLParamOptionsの3番目のパラメータである*pirowです。